package com.wlyuan.open.domain.client.factory;

import cn.hutool.core.util.RandomUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.wlyuan.core.domain.valueobj.Mobile;
import com.wlyuan.open.domain.client.OpenClient;
import com.wlyuan.open.domain.client.respository.OpenClientRepository;
import com.wlyuan.open.dto.api.OpenClientLoginDTO;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import lombok.var;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import java.util.Map;
import java.util.Optional;

/**
 * @author lijing
 */
@Service
@Slf4j
@RequiredArgsConstructor
public class OpenClientFactory {
    private final OpenClientRepository openClientRepository;
    private final PasswordEncoder passwordEncoder;

    private String generateAppId() {
        return RandomUtil.randomString(32);
    }

    public String generateAppSecret() {
        return RandomUtil.randomString(32);
    }

    private String appSecretKey = "appSecret";

    public OpenClient create(OpenClientLoginDTO loginDTO) {
        logger.info("创建开放应用: {}", loginDTO);
        var appId = generateAppId();
        String sourceRaw = JSON.toJSONString(loginDTO);
        OpenClient openClient = new OpenClient(appId, null);
        openClient.init(new Mobile(loginDTO.getMobile()));
        var appSecret = generateAppSecret();
        openClient.changeSecret(appSecret, passwordEncoder);
        //将appSecret存入raw中
        openClient.changeRaw(raw(sourceRaw, appSecret));
        openClientRepository.save(openClient);
        return openClient;
    }

    /**
     * 重置appSecret
     *
     * @param application
     * @return
     */
    public OpenClient changeAppSecret(OpenClient application) {
        var appSecret = generateAppSecret();
        application.changeSecret(appSecret, passwordEncoder);
        application.changeRaw(raw(application.getSourceRaw(), appSecret));
        openClientRepository.save(application);
        return application;
    }

    public String getAppSecretKey(OpenClient application) {
        return Optional.ofNullable(application).map(OpenClient::getSourceRaw).map(raw -> {
            Map<String, Object> sourceMap = JSON.parseObject(raw, Map.class);
            var appSecret = sourceMap.get(appSecretKey);
            return Optional.ofNullable(appSecret).map(secret -> {
                //只显示一次，移除后重新保存
                removeAppSecret(application);
                return secret.toString();
            }).orElse(null);
        }).orElse(null);
    }

    /**
     * appSecret只显示一次，获取之后从raw中移除
     *
     * @param application
     * @return
     */
    private OpenClient removeAppSecret(OpenClient application) {
        Map<String, Object> sourceMap = JSON.parseObject(application.getSourceRaw(), Map.class);
        //appSecret只显示一次，获取之后从raw中移除
        sourceMap.remove(appSecretKey);
        application.changeRaw(JSON.toJSONString(sourceMap));
        openClientRepository.save(application);
        return application;
    }

    private String raw(String sourceRaw, String appSecret) {
        JSONObject jsonObject = JSON.parseObject(sourceRaw);
        jsonObject.put(appSecretKey, appSecret);
        return JSON.toJSONString(jsonObject);
    }
}
